# -*- encoding: utf-8 -*-
"""
@Author     :   zYx.Tom
@Contact    :   526614962@qq.com
@site       :   https://zhuyuanxiang.github.io
---------------------------
@Software   :   PyCharm
@Project    :   NLTK-Python-CN
@File       :   C0604.py
@Version    :   v0.1
@Time       :   2020-11-24 11:00
@License    :   (C)Copyright 2018-2020, zYx.Tom
@Reference  :   
@Desc       :   
@理解：
"""
import math

import nltk


# Chap6 学习分类文本
# 学习目标：
# 1.  识别出语言数据中可以用于分类的特征
# 2.  构建用于自动执行语言处理任务的语言模型
# 3.  从语言模型中学习与语言相关的知识

# 6.4 决策树
# 为输入值选择标签的简单流程图。
# 流程图是由检查特征值的决策节点和分配标签的叶节点组成。（P263 图6-4）
# 决策树桩：是只有一个节点的决策树，基于单个特征来决定如何为输入分类。
# 每个可能的特征值包含一个叶子，并为特征输入指定的类标签。

# 基于决策树桩来生成决策树算法模型：
# 1）选择分类任务的整体最佳的决策树桩
# 2）在训练集上检查每个叶子的准确度。
#       没有达到足够准确度的叶子会被新的决策树桩替换，
#       新的决策树桩是在训练语料的子集上训练的，
#       这些训练语库都是根据到叶子的路径来选择的。

# 6.4.1 熵和信息增益
# 使用信息增益来确定决策树桩最有信息量的特征。
# 信息增益：就是原来的熵送去新减少的熵。
#   信息增益越高，将输入值分为相关组的决策树桩，通过选择具有最高信息增益的决策树桩来建立决策树
# 决策树模型的优点：
#   简单明了，容易理解。
# 决策树模型的缺点：
#   基于分支划分数据过多后，导致数据量不足，产生过拟合；
#   强迫特征按照特定的顺序进行检查（不利用相对独立的特征分类）


# P265.Ex6-8 计算标签链表的熵
def entropy(labels):
    freqdist = nltk.FreqDist(labels)
    probs = [freqdist.freq(l) for l in nltk.FreqDist(labels)]
    return -sum([p * math.log(p, 2) for p in probs])


print(entropy(['male', 'male', 'male', 'male']))
print(entropy(['male', 'female', 'male', 'male']))
print(entropy(['male', 'female', 'male', 'female']))

# 6.5 朴素贝叶斯分类器
# 在朴素贝叶斯分类器中，每个特征都有发言权（避免了决策树中数据量小的特征被忽略的问题）

# 6.5.1 潜在概率模型：为输入选择最有可能的标签
# 基于假设：每个输入值都是经过先为该输入值选择类标签，然后产生每个特征的方式而产生的，每个特征与其他特征都是完全独立的。

# 6.5.2 零计数和平滑
# 建立朴素贝叶斯模型时，因为特征过多可能会产生零计数（稀疏数据），需要采用平滑技术，使得每个特征都有计数。
# nltk.probability提供了多种平滑技术支持。

# 6.5.3 非二元特征的解决办法
# 1）利用装箱技术将之转换为二元特征
# 2）使用回归方法来模拟数字特征的概率

# 6.5.4 独立的朴素性：朴素（naive，天真）的原因是不切实际地假设所有的特征都是朴素独立的

# 6.5.5 双重计数的原因：在训练过程中特征的贡献被分开计算，但是当使用分类器为新输入选择标签时，这些特征的贡献就被组合在一起了。

# 6.6 最大熵分类器：找出能使训练语料的整体似然性最大的参数组。
# 最大熵分类器与朴素贝叶斯分类器使用的模型相似：
# * 朴素贝叶斯分类器使用概率设计模型的参数
# * 最大熵分类器使用搜索技术找出一组能够最大限度地提高分类器性能的参数
# 最大熵分类器使用迭代优化技术选择模型参数

# 6.6.1 最大熵模型：是朴素贝叶斯模型的泛化。
# 朴素贝叶斯模型为每个标签定义一个参数，指定其先验概率，为每个（特征，标签）对定义一个参数，为标签的似然性指定其独立特征的贡献。
# 最大熵模型让用户来判断使用什么样的参数来组合标签和特征。
# 单独的参数既可以将一个特征和多个标签关联起来，也可以将一个特征与一个给定的标签关联起来。即允许模型“概括”相关的标签或特征之间的差异。
# 每个标签和特征的组合都可以接收其自身的参数，并称之为联合特征。联合特征是加了标签值的属性，而（简单）特征是未加标签值的属性。
# 用来构建最大熵模型的联合特征完全反映了朴素贝叶斯模型所使用的联合特征，即最大熵模型的特征比朴素贝叶斯模型的特征更加复杂，也更加多样。

# 6.6.2 最大化熵
# 最大熵原理是指在已知的分布下，选择熵最高的分布。

# 6.6.3 生成式分类器 与 条件式分类器
# 朴素贝叶斯分类器是一个生成式分类器，可以回答以下的问题：
# 1）一个给定的输入的最可能的标签是什么？
# 2）对于一个给定输入，一个给定标签有多大可能性？
# 3）最有可能的输入值是多少？
# 4）一个给定输入值的可能性有多大？
# 5）一个给定输入具有一个给定标签的可能性有多大？
# 6）对于一个可能有两个值的输入，最可能的标签是什么？
# 最大熵分类器是一个条件式分类器
# 条件式分类器建立模型预测：一个给定输入值的标签的概率，只能回答问题1~2
# 生成式模型 比 条件式模型 更加强大，但是计算代价也更大

# 6.7 为语言模型建模
# 模型可以采用：
#   1）监督式分类技术；
#   2）分析型激励模型
# 模型的目的：
#   1）了解语言模型；
#   2）预测新的语言数据

# 6.7.1 模型能够告诉我们什么？
# 描述型模型
#   捕获数据中的模式，不提供任何有关数据包含这些模式的原因；
#   提供数据内相关信息
# 解释型模型
#   试图捕获造成语言模式的属性和关系；
#   提供假设因果关系

# 大多数从语料库中自动构建的模型都是描述型模型。可以用来预测未来的数据，不考虑假设的因果关系。

# 6.8 小结
# 在语料库的语言数据建模，可以帮助理解语言模型，也可以用于预测新的语言数据
# -   监督式分类器的构建：使用加标签的训练语料库来建立模型，该模型可以基于输入数据的特征，预测该输入数据的标签
# -   监督式分类器的应用：文档分类、词性标注、语句分割、对话行为类型识别、确定蕴涵关系等等
# -   监督式分类器的训练：应该把语料分为3个数据集：训练集、开发测试集和测试集
# -   监督式分类器的评估：应该使用训练集和开发测试集中没有使用的数据

# 决策树是自动构建树结构的流程图，用于基于输入数据的特征添加标签。
#   优点是易于解释，缺点是不适合在决策合适标签过程中处理朴素影响的特征值。

# 朴素贝叶斯分类器中每个特征独立地决定应该使用哪个标签。
#   优点是允许特征值间有关系，缺点是当两个或者更多的特征高度相关时将会出现问题。

# 最大熵分类器使用的基本模型与朴素贝叶斯分类器相似
#   优点是不再强调特征独立性假设，并且允许更加复杂的特征组合；
#   缺点是需要通过迭代优化技术寻找使训练集概率最大化的特征权值集合，并且不同的初值会得到不同的优化结果，并且可能只是局部最优。

# 大多数从语料库中自动构建的模型都是描述型模型。
#   只能描述哪些特征与给定的模式或者结构相关，不能给出这些特征与模式之间的因果关系。
